package cate.game.activity.converthero;

import cate.common.table.activity.converthero.row.ConvertConsumeRow;
import cate.common.table.activity.converthero.row.ConvertHeroBaseRow;
import cate.common.table.d.GDOperation;
import cate.common.util.GameResult;
import cate.game.activity.base.core.RoleActivitySingle;
import cate.game.activity.converthero.msg.ConvertHeroActivityInfoResp;
import cate.game.client.msg.MergeMsgSender;
import cate.game.notice.msg.NoticeDialogResp;
import cate.game.res.MixRes;
import cate.game.res.MixResItem;
import cate.game.res.RewardShow;
import cate.game.role.Role;
import cate.game.role.bag.hero.Hero;
import cate.game.train.hero.TrainHeroHandler;
import com.fasterxml.jackson.annotation.JsonIgnore;
import easy.java.dev.note.NoteClass;
import easy.java.dev.note.NoteField;
import easy.java.practice.errorcode.EcResult;

import java.beans.Transient;
import java.util.*;
import java.util.stream.Collectors;

@NoteClass("英雄兑换活动")
public class ConvertHeroActivity extends RoleActivitySingle {
    @NoteField("兑换记录,key:配置id，value:购买次数")
    public Map<Integer, Integer> record;


    public GameResult<ConvertHeroActivity> convert(int tid, Set<String> uids) {
        GameResult<ConvertHeroActivity> r = new GameResult<>();
        r.data = this;
        if (!record.containsKey(tid)) {
            return r.fail("无此项");
        }

        ConvertHeroBaseRow row = getRow(tid);
        if (row == null) {
            return r.fail("找不到配置");
        }
        if (record.get(tid) >= row.limit) {
            return r.fail("已无兑换次数");
        }
        if (uids.size() != row.costNum) {
            return r.fail("英雄数量有误");
        }
        List<Hero> heroes = uids.stream().map(uid -> {
            GameResult<Hero> hr = findHeroResult(role, uid);
            if (hr.ok()) {
                return hr.data;
            } else {
                return null;
            }
        }).filter(Objects::nonNull).collect(Collectors.toList());
        if (heroes.size() < row.costNum) {
            return r.fail("找不到英雄");
        }
        List<Integer> heroPool = getPoolByGroup(row.group).stream().map(cost -> cost.heroId).collect(Collectors.toList());
        if (!heroPool.containsAll(heroes.stream().map(hero -> hero.getTpl(role.getGame()).getTemplateId()).collect(Collectors.toList()))) {
            return r.fail("有不可用于兑换的英雄");
        }
        for (Hero hero :
                heroes) {
            EcResult<Void> or = role.getGame().train.hero.fastOffHero(role, hero.uid);
            if (!or.ok()) {
                return r.fail(or);
            }
            if (hero.lock.islocked()) {
                return r.fail("有英雄已被锁定");
            }
        }
        //先消耗材料
        MergeMsgSender sender = new MergeMsgSender();
        GameResult<MixResItem> c = new MixRes(row.costStr).consume(role, null, sender);
        if (!c.ok()) {
            return r.fail(c);
        }
        // 消耗英雄
        EcResult<RewardShow> returnRes = TrainHeroHandler.calReturn(role, heroes, TrainHeroHandler.convertHeroOpt());
        // 移除英雄
        for (String costUid : uids) {
            role.getBag().hero.removeItem(costUid, sender);
        }
        sender.send(role, true);
        MixRes reward = new MixRes(row.targetStr);
        reward.add(role, true, GDOperation.CONVERT_HERO, tid);
        if (returnRes.ok() && returnRes.data != null && !returnRes.data.isEmpty()) {
            returnRes.data.addTplRwd(reward);
            role.getGame().notice.dialog(role, NoticeDialogResp.TYPE_REWARD, "恭喜获得", 0, returnRes.data.tplRwd, returnRes.data.insRwd);
        } else {
            role.getGame().notice.dialogReward(role, reward);
        }
        Integer times = record.getOrDefault(tid, 0);
        times++;
        record.put(tid, times);
        return r;
    }


    private GameResult<Hero> findHeroResult(Role role, String uid) {
        GameResult<Hero> r = new GameResult<>();
        Hero hero = role.getBag().hero.getItem(uid);
        if (hero == null) {
            return r.fail("英雄不存在！");
        }
        r.data = hero;
        return r.success();
    }


    @Override
    public void initialize(Role role) {
        super.initialize(role);
        if (record == null) {
            record = new HashMap<>();
        }
    }

    @Override
    public void onRoleOpen() {

    }

    @Override
    public void onRoleEnd() {
        record.clear();
    }

    @Override
    public void initSend() {
        noticeUpdate();
    }

    public void noticeUpdate() {
        role.sendNow(new ConvertHeroActivityInfoResp(this));
    }

    @Override
    public void excelCheck() {
        Map<Integer, ConvertHeroBaseRow> configs = getListByConfig(configTid()).stream().collect(Collectors.toMap(row -> row.id, row -> row));
        if (configs.isEmpty()) {
            record.clear();
            return;
        }
        record.entrySet().removeIf(kv -> !configs.containsKey(kv.getKey()));
        for (ConvertHeroBaseRow config : configs.values()) {
            if (!record.containsKey(config.id)) {
                record.put(config.id, 0);
            }
        }
    }

    @JsonIgnore
    @Transient
    private ConvertHeroBaseRow getRow(int id) {
        return role.getGame().table.convertHero.base.get(id);
    }

    @JsonIgnore
    @Transient
    private List<ConvertHeroBaseRow> getListByConfig(final int configId) {
        return role.getGame().table.convertHero.base.getListByConfig(configId);
    }

    @JsonIgnore
    @Transient
    private List<ConvertConsumeRow> getPoolByGroup(int group) {
        return role.getGame().table.convertHero.consume.getRowsByGroup(group);
    }
}
